package jk.fox.node.rule;

import jk.fox.node.node.NodeServer;
import jk.fox.node.node.RpcNode;
import org.apache.log4j.Logger;

import java.util.List;
import java.util.concurrent.atomic.AtomicInteger;
import java.util.concurrent.locks.Lock;
import java.util.concurrent.locks.ReentrantLock;

/**
 * @Auther cuichao
 * @Description: RoundRobinRule
 * @Date: create in 2020/4/19 23:24
 */
public class RoundRobinRule implements IRule<RpcNode> {


    private static Logger logger = Logger.getLogger(RoundRobinRule.class);

    private AtomicInteger counter;
    private Lock lock = new ReentrantLock();


    public RoundRobinRule(){
        super();
        counter = new AtomicInteger(0);
    }

    @Override
    public String rule(RpcNode node) {
        List<String> uriList = node.getUriList();

        int i = 0;

        while (i++ < 10){

            if(uriList ==null || uriList.isEmpty()){
               return null;
            }

            int position = incrementAndGet(uriList.size());


            if(position >= uriList.size()){
                logger.warn(String.format("RoundRobinRule has choose index is %d, but the list size is %d",position ,uriList.size()));
                continue;
            }

            String url = uriList.get(position);

            NodeServer server = node.getServer(url);

            if(!server.isAlive()){
                continue;
            }
            logger.info(String.format("RoundRobinRule has choose alive NodeServer is %s",url));

            return url;
        }
        logger.warn("RoundRobinRule is no available server to choose");

        return null;
    }

    @Override
    public String getName() {
        return " round-robin";
    }

    protected int incrementAndGet(int limit) {
        for (;;) {
            int current = counter.get();
            int next = (current + 1) % limit;
            if (counter.compareAndSet(current, next))
                return next;
        }
    }


/*

    public String oldRule(RpcNode node) {
        List<String> uriList = node.getUriList();
        if(uriList.isEmpty() || uriList.size() < 1){
            throw new NullPointerException(node.getDomain()+"没有可用服务地址");
        }
        if(uriList.size() == 1){
            return uriList.toArray()[0].toString();
        }
        Object[] objects = uriList.toArray();
        int limit = uriList.size() - 1;
        int position = counter.get();

        if(position == limit){
            lock.lock();
            try {
                if(counter.get() == limit){
                    counter.set(0);
                    position = limit;
                }
            }finally {
                lock.unlock();
            }
        }
        counter.getAndIncrement();

        return objects[position].toString();
    }

*/




}
